//
//  ZHWebPage.m
//  Pod
//
//  Created by Basic on 16/10/16.
//  Copyright © 2016年 naruto. All rights reserved.
//


#import "ZHWebPage.h"
#import "ZHWebBridgeTask.h"
#import "BCRouteUtils.h"
#import "BCRouteKitPrivate.h"
#import "BCRouteKitPublic.h"
#import "BCRouter.h"
#import "NJKWebViewProgress.h"
#import "NJKWebViewProgressView.h"
#import <BCFileLog/BCFileLog.h>
#import <BCComConfigKit/BCComConfigKit.h>
#import <BCUIKit/UIBarButtonItem+BCHelper.h>
#import <BCFoundation/BCFoundation.h>
#import <BCUIKit/UIView+BCHelper.h>


@interface ZHWebPage () <WKNavigationDelegate, WKUIDelegate, NJKWebViewProgressDelegate, WKScriptMessageHandler>
@property (nonatomic, strong) NJKWebViewProgressView    *progressView;
@property (nonatomic, strong) NJKWebViewProgress    *progressProxy;
@property (nonatomic, strong) UIBarButtonItem   *backButtonItem;
@property (nonatomic, strong) UIBarButtonItem   *closedButtonItem;

@property (nonatomic, strong) NSMutableURLRequest   *currentRequest;
@property (nonatomic, strong) NSMutableArray<ZHWebBridgeTask *> *listBridges;
@property (nonatomic, strong) NSMutableDictionary   *registerJSObjDict;//交互的js对象 集合
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;

@end

@implementation ZHWebPage
//MARK: - life cycle
+ (void)load {
    BCRouterRegist(kZHRoute_WebPage, NSStringFromClass([self class]));
}
- (instancetype)init {
    self = [super init];
    if (self) {
        self.autoInsertClosed = YES;
    }
    return self;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    _listBridges = [[NSMutableArray<ZHWebBridgeTask *> alloc] init];
    _registerJSObjDict = [[NSMutableDictionary alloc] init];
    [self initSubViews];
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if(self.showNavigationBar){
        [self.navigationController setNavigationBarHidden:NO animated:NO];
    }else{
        [self.navigationController setNavigationBarHidden:YES animated:NO];
    }

    for (ZHWebBridgeTask *task in self.listBridges) {
        if (!_registerJSObjDict[task.ObjName]) {//判断是否已经注册过
            _registerJSObjDict[task.ObjName] = @(YES);
            [self.webView.configuration.userContentController addScriptMessageHandler:self name:task.ObjName];
        }
        
    }
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [self.navigationController setNavigationBarHidden:NO animated:YES];
}
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    for (ZHWebBridgeTask *task in self.listBridges) {
        [self.webView.configuration.userContentController removeScriptMessageHandlerForName:task.ObjName];
        _registerJSObjDict[task.ObjName] = nil;
    }
}
- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    if (self.showIndicator) {
        self.activityIndicator.center = CGPointMake(self.view.center.x, self.view.center.y-kBCNAVBAR_HEIGHT);
    }
    if (self.showNavigationBar) {

        self.webView.bc_y = 88;
    }
}
- (void)dealloc {
    [self cleanWebCache];
}

//MARK: - 初始化sub view
- (void)initSubViews
{
    [self.view addSubview:self.webView];
//    self.webView.translatesAutoresizingMaskIntoConstraints = NO;
//
//    [NSLayoutConstraint activateConstraints:@[
//        [self.webView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
//        [self.webView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
//        [self.webView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
//        [self.webView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
//    ]];

    if (!self.hideProgress) {
        [self.navigationController.navigationBar addSubview:self.progressView];
    }
    if (self.showIndicator) {
        [self.view addSubview:self.activityIndicator];
    }
    if (self.hideBack || self.rootPage) {
        self.navigationItem.leftBarButtonItems = nil;
    }else{
        self.navigationItem.leftBarButtonItems = @[self.backButtonItem];
    }

    BCLogInfo(@"[web] load url:%@",_url);
    if (self.localHtmlString.length>0) {
        //使用本地 html
        [self.webView loadHTMLString:[self loadLocalCssWithMobileHeader] baseURL:self.localBaseURL];
    } else {
        [self.webView loadRequest:self.currentRequest];
    }
    //添加默认监听
    [self prepareBridges];
}
// 添加本地html js
- (NSString *)loadLocalCssWithMobileHeader {
    NSString *cssPath = [[NSBundle mainBundle] pathForResource:@"quill.snow" ofType:@"css"];
    if (!cssPath) {
        return self.localHtmlString;
    }
    NSString *headString = @"<!DOCTYPE>\n<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
    NSString *cssString = [NSString stringWithFormat:@"\n<link rel=\"stylesheet\" type=\"text/css\" href=\"%@\">\n",cssPath];
    NSString *imageStyleString = @"<style>img {max-width: 100%;text-align:center} body {overflow-y: scroll !important;word-wrap:break-word}</style>";
    NSString *result = [NSString stringWithFormat:@"%@%@%@</head>\n<div class=\"ql-editor\">\n%@\n</div>\n</html>",headString,cssString,imageStyleString,self.localHtmlString];
    
    return result;
}
- (void)cleanWebCache
{
    [_listBridges removeAllObjects];
    if (_webView) {
        _webView.UIDelegate = nil;
        _webView.navigationDelegate = nil;
        [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
        [_webView removeObserver:self forKeyPath:@"title"];
        [_webView scrollView].delegate = nil;
        [_webView stopLoading];
        [_webView loadHTMLString:@"" baseURL:nil];
        [_webView stopLoading];
        [_webView removeFromSuperview];
        _webView = nil;
    }

    
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    
    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
    [[NSURLCache sharedURLCache] removeCachedResponseForRequest:self.currentRequest];
    
    [self.progressView removeFromSuperview];
}

/**
 webview 是否可以倒退（不是一个页面,可以js回退）

 @param webview webview description
 @param url url description
 @return return value description
 */
- (BOOL)webViewGoBack:(WKWebView *)webview url:(NSString *)url {
    // 对比初始url
    if ([webview.backForwardList.currentItem.URL.absoluteString isEqualToString:self.url]) {
        return NO;
    }
    return [webview canGoBack];
}
//MARK: - setter
- (void)setUrl:(NSString *)url {
    _url = url;
    if (_webView) {
       [self.webView loadRequest:self.currentRequest];
    }
}

//MARK: - getter
-(UIBarButtonItem *)backButtonItem {
    if(!_backButtonItem){
        BCWeakObj(self);
        _backButtonItem = [[UIBarButtonItem alloc] bc_initBackItem:^(UIButton *sender) {
            BCStrongObj(self);
            [self onBackItemAction:sender];
        }];
    }
    return _backButtonItem;
}
-(UIBarButtonItem *)closedButtonItem {
    if(!_closedButtonItem){
        BCWeakObj(self);
        _closedButtonItem = [[UIBarButtonItem alloc] bc_initLeftItem:[BCComConfig.config.navCloseImg imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] highlightImage:nil text:nil textColor:nil action:^(UIButton *sender) {
            BCStrongObj(self);
            [self onCloseItemAction:sender];
        }];
    }
    return _closedButtonItem;
}
-(NJKWebViewProgress *)progressProxy {
    if(!_progressProxy){
        _progressProxy = [[NJKWebViewProgress alloc] init];
        _progressProxy.progressDelegate = self;
    }
    return _progressProxy;
}
-(NJKWebViewProgressView *)progressView {
    if(!_progressView){
        CGFloat progressBarHeight = 2.f;
        CGRect navigaitonBarBounds = self.navigationController.navigationBar.bounds;
        CGRect barFrame = CGRectMake(0, navigaitonBarBounds.size.height - progressBarHeight, navigaitonBarBounds.size.width, progressBarHeight);
        _progressView = [[NJKWebViewProgressView alloc] initWithFrame:barFrame];
        _progressView.progressBarView.backgroundColor = BCComConfig.config.navProgressColor;
        _progressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
    }
    return _progressView;
}
- (UIActivityIndicatorView *)activityIndicator {
    if (!_activityIndicator) {
        _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
        _activityIndicator.center = self.view.center;
        _activityIndicator.color = [UIColor blackColor];
        _activityIndicator.hidesWhenStopped = YES;
    }
    return _activityIndicator;
}
-(WKWebView *)webView {
    if(!_webView){
        //设置cookies
        __block NSMutableString *cookieStr = [[NSMutableString alloc] init];
        NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
        [cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [cookieStr appendFormat:@"document.cookie='%@=%@;path=/';",obj.name,obj.value];
        }];
        if (self.cookies) {
            [self.cookies enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
                [cookieStr appendFormat:@"document.cookie='%@=%@;path=/';",key, obj];
            }];
        }
        NSString *jScript = (NSString *)cookieStr;
        WKUserScript* wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
        WKUserContentController *wkUController = [[WKUserContentController alloc] init];
        [wkUController addUserScript:wkUScript];
        WKWebViewConfiguration* wkWebConfig = [[WKWebViewConfiguration alloc] init];
        wkWebConfig.userContentController = wkUController;
//        wkWebConfig.suppressesIncrementalRendering = YES; // 是否支持记忆读wkWebConfig
//       [wkWebConfig.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
//        if (@available(iOS 10.0, *)) {
//             [wkWebConfig setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"];
//        }
//        WKPreferences *preference = [[WKPreferences alloc]init];
//        // 设置字体大小(最小的字体大小)
//        preference.minimumFontSize = 17;
//        // 设置偏好设置对象
//        wkWebConfig.preferences = preference;
        
        _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:wkWebConfig];
        [_webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
        _webView.UIDelegate = self;
        _webView.navigationDelegate = self;
        _webView.backgroundColor = [UIColor clearColor];
        _webView.opaque = NO;
        _webView.scrollView.showsVerticalScrollIndicator = NO;
        [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
        [_webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];
        [_webView setFrame:self.view.bounds];
        if (@available(iOS 11.0, *)) {
            _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        } else {
            self.automaticallyAdjustsScrollViewInsets = NO;
        }
    }
    return _webView;
}
-(NSMutableURLRequest *)currentRequest {
    if(!_currentRequest && _url){
        //先处理URL
        NSString *strURLAdd = nil;
        //add ts
        if(![_url containsString:@"ts="]){
            long long reqTs = [[NSDate date] timeIntervalSince1970]*1000;
            strURLAdd = [NSString stringWithFormat:@"ts=%@",@(reqTs)];
        }
        
        if(strURLAdd.length>0){
            if(![_url containsString:@"?"]){
                //请求的url没有？
                _url = [NSString stringWithFormat:@"%@?%@",_url,strURLAdd];
            }
            else{
                //请求的url有？
                _url = [NSString stringWithFormat:@"%@&%@",_url,strURLAdd];
            }
        }
        _url = [NSString bc_getValidURL:_url];//过滤非法url
        if(_url.length<=0){
            BCLog(@"[web] error url");
        }
        NSURL *requestURL = [NSURL URLWithString:_url];
        if(!requestURL){
            BCLog(@"[web] error request");
        }
        _currentRequest = [[NSMutableURLRequest alloc] initWithURL:requestURL];
        if (self.headers) {
            for (NSString *key in self.headers.allKeys) {
                NSString *value = self.headers[key];
                if (value.length > 0) {
                    [_currentRequest setValue:value forHTTPHeaderField:key];
                }
            }
        }
    }
    return _currentRequest;
}


//MARK: - 添加js调用oc 的bridge 任务
-(void)prepareBridges {
    //子类重写
    // 添加打开外链桥接
    [self addBridgeHandler:@"openLink" action:^(NSString *url) {
        if (url.length > 0 && [url isKindOfClass:[NSString class]]) {
             [[BCRouter sharedInstance] pushRoute:url];
        }
    }];

    /// 中药对接
    [self addBridgeHandler:@"jumpToActivity" action:^(id msgBody) {
        // 回调处理
        id<BCRouteWebProtocol> webDelegate = [BCRouter sharedInstance].webDelegate;
        if (webDelegate && [webDelegate respondsToSelector:@selector(bcroute:webBridg:messageBody:)]) {
            [webDelegate bcroute:[BCRouter sharedInstance] webBridg:@"jumpToActivity" messageBody:msgBody];
        }
    }];
}
- (void)addBridgeHandler:(NSString *)ObjName action:(void (^)(id msgBody))action {
    ZHWebBridgeTask *bridgeTask = [[ZHWebBridgeTask alloc] init];
    bridgeTask.ObjName = ObjName;
    [bridgeTask setBridgeAction:action];
    [self.listBridges addObject:bridgeTask];
}

//MARK: - oc 调用js
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError * error))completionHandler {
    [self.webView evaluateJavaScript:javaScriptString completionHandler:completionHandler];
}


//MARK: - Event
- (void)onBackItemAction:(id)sender {
    if (self.rootPage) {
        [_webView goBack];
        return;
    }
    BOOL canGoBack = [self webViewGoBack:_webView url:_url];
    if (canGoBack) {
        if (self.autoInsertClosed && self.navigationItem.leftBarButtonItems.count < 2) {
            self.navigationItem.leftBarButtonItems = @[ self.backButtonItem, self.closedButtonItem ];
        }
        [_webView goBack];
    }
    else {
        [self onCloseItemAction:sender];
    }
}
- (void)onCloseItemAction:(id)sender {
    if (self.navigationController.viewControllers.count == 1) {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    else {
        [self.navigationController popViewControllerAnimated:YES];
    }
}
///MARK: - private method
// 在跳转过程中增加返回 暂时支持跟页面配置
- (void)addBackNavigation {
    if (!self.rootPage) {
        return;
    }
    BOOL canGoBack = [self.webView canGoBack] || self.webView.backForwardList.backList.count;
    if (canGoBack) {
        self.navigationItem.leftBarButtonItem = self.backButtonItem;
        
    }else{
        self.navigationItem.leftBarButtonItems = nil;
    }
}

//MARK: - observe
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
    if (!self.hideProgress &&[keyPath isEqualToString:@"estimatedProgress"]) {
        float progress = [change[NSKeyValueChangeNewKey] floatValue];
        [_progressView setProgress:progress animated:YES];
    }
    else if (!self.fixedTitle && [keyPath isEqualToString:@"title"]) {
        //没有固定标题
        if (self.navigationController) {
            self.navigationItem.title = change[NSKeyValueChangeNewKey];
        }
    } else if ([keyPath isEqualToString:@"URL"]) {

    }
}


//MARK: - NJKWebViewProgress Delegate
- (void)webViewProgress:(NJKWebViewProgress*)webViewProgress updateProgress:(float)progress {
    if (self.hideProgress) {
        return;
    }
    [_progressView setProgress:progress animated:YES];
}

//MARK: - WKWebView delegate
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    BCLogInfo(@"[http] receive%@",message.body);
    if(message.name.length<=0 || !message.body){
        return;
    }
    NSString *objName = message.name;
    for (ZHWebBridgeTask *task in self.listBridges) {
        if ([objName isEqualToString:task.ObjName]){//找到要执行的对象
            // message.body进行了encode操作路由无法解析 需要进行decoded
//            NSString *bodyString = [NSString stringWithFormat:@"%@",message.body];
//#pragma clang diagnostic push
//#pragma clang diagnostic ignored "-Wdeprecated-declarations"
//            NSString *decodedString=(__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)bodyString, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
//#pragma clang diagnostic pop
            task.bridgeAction(message.body);
            break;
        }
    }
}
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
    
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
    }];
    [alertController addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
    }])];
    
    [self presentViewController:alertController animated:YES completion:nil];
}

//MARK: - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    if (navigationAction.targetFrame == nil) {
        [webView loadRequest:navigationAction.request];
    }
    decisionHandler(WKNavigationActionPolicyAllow);

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self addBackNavigation];
        
    });
}

// 解决网页中有target="_blank" 在新窗口打开链接的一种方法
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView loadRequest:navigationAction.request];
    }
    return nil;
}
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    if (self.showIndicator) {
        [self.activityIndicator startAnimating];
    }
    BCLogInfoStr(@"【WKWebView】Start");
}
 // 页面加载失败时调用
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    BCLogInfo(@"[http] load err:%@",[error userInfo]);
    if (!self.fixedTitle && self.navigationItem.title.length<=0 && self.navigationController) {
        self.navigationItem.title = BCLOC(@"加载出错啦");
    }
    
    if (self.showIndicator) {
        [self.activityIndicator stopAnimating];
    }
}
  // 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    if (self.showIndicator) {
        [self.activityIndicator stopAnimating];
    }
    BCLogInfoStr(@"【WKWebView】Finish");
}
@end
